package com.amos.log.configure.aspect;

import com.amos.log.configure.properties.LogProperties;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.UUID;

/**
 * @ClassName : WebLogAspect
 * @Description : web日志拦截，记录请求日志，响应日志
 * @Author : tianshuo
 * @Date: 2020-11-12 18:19
 */

@Aspect
public class LogAspect {
    private static Logger log = LoggerFactory.getLogger(LogAspect.class);


    private String logName;
    private  String aspectExpression ="";

    public LogAspect(LogProperties logProperties) {
        this.logName = logProperties.getLogName();
        this.aspectExpression = logProperties.getAspectExpression();
        log.info("日志名称：{} , 表达式：{}",logName,aspectExpression);
    }

    private ThreadLocal<Long> startTime = new ThreadLocal<>();
    private ThreadLocal<String> logId = new ThreadLocal<>();




    @Pointcut(value = "execution(public * com.*.controller.*.*(..))")
    public void pointcut() {

    }

    @Before("pointcut()")
    public void doBefore(JoinPoint joinPoint){
        startTime.set(System.currentTimeMillis());
        logId.set(UUID.randomUUID().toString());
        //获得类名
        String clazzName = joinPoint.getTarget().getClass().getSimpleName();
        //获得方法名
        String methodName = joinPoint.getSignature().getName();

        // 接收到请求，记录请求内容
        log.info("[{},{}.{}] 请求开始.",logId.get(), clazzName, methodName);

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

        HttpServletRequest request = attributes.getRequest();


        // 记录下请求内容
        log.info("[{}] URL : {}" ,logId.get(), request.getRequestURL().toString());
        log.info("[{}] HTTP_METHOD : {}" ,logId.get(), request.getMethod());
        log.info("[{}] IP : {}" ,logId.get(), request.getRemoteAddr());
        log.info("[{}] CLASS_METHOD : {}.{}",logId.get() , clazzName,methodName);
        log.info("[{}] ARGS : {}" ,logId.get(), Arrays.toString(joinPoint.getArgs()));

    }



    @AfterReturning(value = "pointcut()", returning = "response")
    public void logAfterRunning(JoinPoint joinPoint, Object response) {
        //获得类名
        String clazzName = joinPoint.getTarget().getClass().getSimpleName();
        //获得方法名
        String methodName = joinPoint.getSignature().getName();
        log.info("[{},{}.{}] 请求结束，耗时(毫秒):{},响应信息: \n\t {}. ",logId.get(), clazzName, methodName,
                (System.currentTimeMillis() - startTime.get()),response == null ? "" : response.toString());
        startTime.remove();
        logId.remove();
    }

    /**
     * @description  在连接点执行之后执行的通知（异常通知）
     */
    @AfterThrowing("pointcut()")
    public void doAfterThrowingGame(){
        log.info("[{}] 请求异常,耗时(毫秒):{}",logId.get(),(System.currentTimeMillis() - startTime.get()));
        startTime.remove();
        logId.remove();
    }


}

